<?php
declare (strict_types = 1);

namespace app;
use app\common\traits\JumpTrait;

use think\App;
use think\exception\ValidateException;
use think\Validate;
use think\facade\View;

/**
 * 控制器基础类
 */
abstract class BaseController {
	
	use JumpTrait; //控制跳转的组件
	
    /**
     * Request实例
     * @var \think\Request
     */
    protected $request;

    /**
     * 应用实例
     * @var \think\App
     */
    protected $app;

    /**
     * 是否批量验证
     * @var bool
     */
    protected $batchValidate = false;

    /**
     * 控制器中间件
     * @var array
     */
    protected $middleware = [];

	protected $nowtime;
	protected $tdtime;
	protected $montime;
	
    /**
     * 构造方法
     * @access public
     * @param  App  $app  应用对象
     */
    public function __construct(App $app) {
	    //echo 'base,__construct';
        $this->app     = $app;
        $this->request = $this->app->request;
		$this->requestInfo();
		
        // 控制器初始化
        $this->initialize();
    }

    // 初始化
    protected function initialize() {
		$time = time();
		$this->nowtime = $time;
		$this->tdtime = str2time(date('Y-m-d'));
		$this->montime = str2time(date('Y-m'));
		
		//保存和获取配置
		//$this->saveAndGetConfigForSystem();

		//define('EXTEND_PATH', thinkEnv::get('root_path') . 'extend/');
	}

	function saveAndGetConfigForSystem() {
		$sys_identify = 'system_config';
		$configInfo = cache($sys_identify);
		if (empty($configInfo)) {
			$configDao = model('common/Config');
			$configInfo = $configDao->getConfigsBySpace('system');
			cache($sys_identify, $configInfo, 3600);
		}
		//echo '<br>系统缓存配置configInfo:';print_r($configInfo);
		$this->configInfo = $configInfo;
		$this->assign('configInfo', $configInfo);
		//添加至全局配置(比如在model里面也能用)
		$cache_config = [];
		$cache_config = $configInfo;
		$cache_config['site_host'] = 'http://'.$_SERVER['HTTP_HOST'];
		thinkConfig::set($cache_config, 'system'); //添加系统配置
	}

	/**
	 * request信息
	 * @return [type] [description]
	 */
	protected function requestInfo() {
		defined('MODULE_NAME') or define('MODULE_NAME', app('http')->getName());
		defined('CONTROLLER_NAME') or define('CONTROLLER_NAME', $this->request->controller());
		defined('ACTION_NAME') or define('ACTION_NAME', $this->request->action());
		defined('IS_POST') or define('IS_POST', $this->request->isPost());
		defined('IS_AJAX') or define('IS_AJAX', $this->request->isAjax());
		defined('IS_PJAX') or define('IS_PJAX', $this->request->isPjax());
		defined('IS_GET') or define('IS_GET', $this->request->isGet());

		//$this->param = $this->request->param();
		//$this->urlRule = strtolower($this->request->module() . '/' . $this->request->controller() . '/' . $this->request->action());
		//$this->ip = $this->request->ip();
		$this->url = $this->request->url(true);//完整url
	}

	function setSeoOrigin($first_name, $sec_name = '') {
		if ($first_name) {
			$site_seo_title = $first_name;
			$site_seo_keywords = $first_name;
			$site_seo_description = $first_name;
		}
		if ($sec_name) {
			$site_seo_title .= '_'.$sec_name;
			$site_seo_keywords .= '_'.$sec_name;
			$site_seo_description .= '_'.$sec_name;
		}
		$this->assign('site_seo_title', $site_seo_title);
		$this->assign('site_seo_keywords', $site_seo_keywords);
		$this->assign('site_seo_description', $site_seo_description);
	}

	//h5upload上传
	public function h5uploadFile($dir, $i, $oldFileUrl) {
		$fileName = I("post.fileName_".$i, '', 'pwEscape');
		$fileType = I("post.fileType_".$i, '', 'pwEscape');
		$fileSize = I("post.fileSize_".$i, '', 'pwEscape');
		$fileData = I("post.fileData_".$i, '', 'pwEscape');

		$h5Upload = new \org\util\H5Upload();
		$h5Upload->saveFtpPath = $dir.'/Mon_'.date('ym') . '/';
		$h5Upload->fileName = $fileName;
		$h5Upload->fileType = $fileType;
		$h5Upload->fileSize = $fileSize;
		$h5Upload->fileData = $fileData;
		if ($oldFileUrl) {
			$h5Upload->oldAttachs = array( //删除旧的附件
				'0' => $oldFileUrl,
			);
		}
		$h5Upload->upload(); //开始上传
		if ($h5Upload->getError()) {
			$this->errorAlertAjax($h5Upload->getError());
		}

		$attachUrl = $h5Upload->getAttachUrl();
		//echo $attachUrl;exit;
		return $attachUrl;
	}

	//h5upload批量上传
	public function h5uploadFilePatch($dir, $delAttachs = '') {
		$fileName = input('post.fileName/a', '', 'pwEscape');
		$fileType = input('post.fileType/a', '', 'pwEscape');
		$fileSize = input('post.fileSize/a', '', 'pwEscape');
		$fileData = input('post.fileData/a', '', 'pwEscape');

		if (!$fileName) {
			return;
		}

		$attachs = array();
		$h5Upload = new \org\util\H5Upload();
		$h5Upload->saveFtpPath = $dir.'/Mon_'.date('ym') . '/';
		foreach ($fileName as $key => $value) {
			$h5Upload->fileName = $fileName[$key];
			$h5Upload->fileType = $fileType[$key];
			$h5Upload->fileSize = $fileSize[$key];
			$h5Upload->fileData = $fileData[$key];
			$h5Upload->upload(); //开始上传
			if ($h5Upload->getError()) {
				$this->error($h5Upload->getError());
			}

			$uploadInfo = $h5Upload->getUploadInfo();

			$attachs[] = array(
				'name'		=> $uploadInfo['name'],
				'attachurl'	=> $uploadInfo['attachurl'],
				'type'		=> $uploadInfo['ext'],
				'size'		=> $uploadInfo['size'],
			);
		}
		if ($delAttachs) {
			if (config('app.ftp_status') == 1) {
				$ftpConfig = config('app.ftp_config');
				$ftp = new \Org\Util\FtpCmd();
				$ftp->init($ftpConfig['server'], $ftpConfig['port'], $ftpConfig['username'], $ftpConfig['password'], $ftpConfig['dir']);

				foreach ($delAttachs as $key => $value) {
					//echo $value;exit;
					$ftp->delete($value);
				}
			}
		}

		//print_r($attachs);exit;
		return $attachs;
	}

	//单个文件上传
	public function comuploadFile($dir, $flag, $delAttach='', $extraData=[], $isRemoveOrigin=1) {
		$upload = new \org\util\UploadFile();
		$upload->keyFlag = $flag;
		//设置上传文件类型
		if (isset($extraData['allowExts'])) {
			$upload->allowExts = explode(',', $extraData['allowExts']);
		} else {
			$upload->allowExts = explode(',', 'jpg,gif,png,jpeg,mp4,m4v,m4a,mov,flv,doc,docx,zip,rar,mp3,mpeg,pdf,ppt,pptx,xls,xlsx');
		}
		//设置附件上传目录
		$upload->savePath = public_path().'data/upload/'; //这个必须要用public下的缓存目录，不然ftp上传时会报Error illegal file type错误，不知道能否改进。
		if (isset($extraData['savepath'])) {
			$upload->saveFtpPath = $dir.'/'.$extraData['savepath'].'/Mon_'.date('ym') . '/';
		} else {
			$upload->saveFtpPath = $dir.'/Mon_'.date('ym') . '/';
		}
		//删除原图
		if ($isRemoveOrigin) {
			$upload->thumbRemoveOrigin = true;
		} else {
			$upload->thumbRemoveOrigin = false;
		}
		//echo 'thumbRemoveOrigin:';$upload->thumbRemoveOrigin;exit;
		if (isset($extraData['maxsize'])) {
			$upload->maxSize = $extraData['maxsize'];
		}
		if (!$upload->upload()) {
			return [500, $upload->getErrorMsg()];
		} else {
			//取得成功上传的文件信息
			$fileInfo = $upload->getFileInfo();
			//echo '文件信息：';print_r($fileInfo);exit;
			//import("@.ORG.Image");
			//给m_缩略图添加水印, Image::water('原文件名','水印图片地址')
			//Image::water($uploadList[0]['savepath'] . 'm_' . $uploadList[0]['savename'], APP_PATH.'Tpl/Public/Images/logo.png');
			//$reuslt = $uploadList[0]['saveFullPath'];
		}
		if ($fileInfo && $delAttach) {
			if (config('app.ftp_status') == 1) {
				$ftpConfig = config('app.ftp_config');
				$ftp = new \org\util\FtpCmd();
				$ftp->init($ftpConfig['server'], $ftpConfig['port'], $ftpConfig['username'], $ftpConfig['password'], $ftpConfig['dir']);
				if (is_array($delAttach)) {
	                foreach ($delAttach as $key => $value) {
	                    if (strpos($value,'..') !== false) {
	                        return false;
	                    }
	                    $ftp->delete($value);
	                    $ftp->delete(graphicsMagick($value));
	                }
				} else {
					$ftp->delete($delAttach);
				}
			}
		}
		if ($fileInfo) {
			//图片删除逻辑
			$isDelOldImg = 0;
			$picurl_del = input('post.'.$flag.'_del', '', 'intval');
			if ($picurl_del) {
				$this->delFtpFile($delAttach);
				$isDelOldImg = 1;
			}
			$fileInfo['isDelOldImg'] = $isDelOldImg;
	        //echo '上传文件信息：';print_r($fileInfo);echo '是否删除：';echo $isDelOldImg;exit;
			return [200, '', $fileInfo];
		} else {
			return [500, '', []];
		}
	}

	//多个文件上传
	public function comuploadFilePatch($dir) {
		$upload = new \org\util\UploadFile();
		//设置上传文件类型
		$upload->allowExts = explode(',', 'jpg,gif,png,jpeg,mp4,mov,flv,doc,docx,zip,rar,mp3,mpeg');
		//设置附件上传目录
		$upload->savePath = CMF_DATA.'/data/upload/';
		$upload->saveFtpPath = $dir.'/Mon_'.date('ym') . '/';
		//删除原图
		$upload->thumbRemoveOrigin = true;
		if (!$upload->upload()) {
			$this->windReturn('error', $upload->getErrorMsg());
		} else {
			//取得成功上传的文件信息
			$uploadList = $upload->getUploadFiles();
			//import("@.ORG.Image");
			//给m_缩略图添加水印, Image::water('原文件名','水印图片地址')
			//Image::water($uploadList[0]['savepath'] . 'm_' . $uploadList[0]['savename'], APP_PATH.'Tpl/Public/Images/logo.png');
			//$reuslt = $uploadList[0]['saveFullPath'];
			return $uploadList;
		}
	}

	//删除附件 2016.05.17
	public function delFtpFile($fileInfo) {
		$ftpConfig = config('app.ftp_config');
		$ftp = new \org\util\FtpCmd();
		$ftp->init($ftpConfig['server'], $ftpConfig['port'], $ftpConfig['username'], $ftpConfig['password'], $ftpConfig['dir']);
		$ftp->delete($fileInfo);
	}

	//删除附件 2016.05.17
	public function delFtpFiles($fileList) {
		$ftpConfig = config('app.ftp_config');
		$ftp = new \org\util\FtpCmd();
		$ftp->init($ftpConfig['server'], $ftpConfig['port'], $ftpConfig['username'], $ftpConfig['password'], $ftpConfig['dir']);
		foreach ($fileList as $key => $value) {
			$ftp->delete($value);
		}
	}

    /**
	 * 优酷视频云：http://cloud.youku.com/
	 * 优酷的视频问题：OAuth2授权的原始方法好像去掉了，用不了，只能手动刷，手动刷的话，登陆网站后，有手动刷的地方。
	 * access_token有效期30天，refresh_token有效期40天
	 * 以当前刷新为准，如果30-40天内，上传视频时，系统会默认刷新access_token；
	 * 但是如果超过40天后，这期间，没有上传视频，系统的access_token会失效，只能去后台手动刷新。
	 */
	public function youkuUpload($flag) {
		if (!$_FILES[$flag]) {
			return;
		}

		$originName = $_FILES[$flag]['name'];
		$tmp_name = $_FILES[$flag]['tmp_name'];

		$mime_types = array(
			'video/mp4'	=> 'mp4',
			'video/mpeg'=> 'mpe',
			'video/quicktime'=> 'mov',
		);
		$type = $_FILES['fileData']['type'];

		$path_parts = pathinfo($_FILES['fileData']['name']);
		//print_r($path_parts);exit;
		if ($path_parts['extension']) {
			$ext = $path_parts['extension'];
		} else {
			if ($mime_types[$type]) {
				$ext = $mime_types[$type];
			} else {
				$ext = 'mp4';
			}
		}

		$filename = "youku_".mt_rand().'.'.$ext;
		$targetVideo = PUBLIC_PATH."data/".$filename;

		//传输文件
		if (!move_uploaded_file($tmp_name, $targetVideo)) {
			$this->error('文件上传保存错误！');
		}

		/*****YoukuUpload SDK*****/
		header('Content-type: text/html; charset=utf-8');
		include(EXTEND_PATH."YoukuUploadSDK/include/YoukuUploader.class.php");

		$client_id = config('youku_id'); // Youku cloud client_id
		$client_secret = config('youku_secret'); //Youku cloud client_secret

		//先获取access_token
		$youkuDao = model('common/YoukuToken');
		$youkuInfo = $youkuDao->getInfo(1);
		//print_r($youkuInfo);exit;
		$access_token = $youkuInfo['access_token'];
		$refresh_token = $youkuInfo['refresh_token'];
		//先获取access_token end

		/*
		**The way with username and password was deprecated!
		**Apply access_token to upload the video file.
		**In addition, refresh_token is to refresh expired access_token.
		**If it is null, the access_token would not be refreshed.
		**You may refresh it by yourself.
		**Like "http://cloud.youku.com/docs?id=109" for reference.
		*/

		$params = [];
		$params['access_token'] = $access_token;
		$params['refresh_token'] = $refresh_token;

		$params['username'] = '13776088607';
		$params['password'] = 'wuyuan123456';

		set_time_limit(0);
		ini_set('memory_limit', '128M');
		$youkuUploader = new \YoukuUploader($client_id, $client_secret);
		$file_name = $targetVideo; //video file
		try {
			$file_md5 = @md5_file($file_name);
			if (!$file_md5) {
				throw new Exception("Could not open the file!\n");
			}
		}catch (Exception $e) {
			echo "(File: ".$e->getFile().", line ".$e->getLine()."): ".$e->getMessage();
			return;
		}
		$file_size = filesize($file_name);
		$uploadInfo = array(
			"title" => $filename, //video title
			"tags" => "demo", //tags, split by space
			"file_name" => $file_name, //video file name
			"file_md5" => $file_md5, //video file's md5sum
			"file_size" => $file_size //video file size
		);
		//print_r($uploadInfo);exit;
		//print_r($params);exit;
		$progress = true; //if true,show the uploading progress
		$videoId = $youkuUploader->upload($progress, $params, $uploadInfo);
		//视频上传完成

		//删除本地视频缓存
		@unlink($targetVideo);

		//获取上传视频信息
		$videoInfo = $youkuUploader->getVideoInfo($videoId);
		//print_r($videoInfo);exit;

		ob_clean();

		// $youkuVideoDao = model('common/YoukuVideo');
		// $data = [
		// 	"uid" => $this->moonuid,
		// 	"username" => $this->moonname,
		// 	"video_id" => $videoId,
		// 	"title" => $filename,
		// 	"tags" => "demo",
		// 	"file_name" => $file_name,
		// 	"file_size" => $file_size,
		// 	"link" => $videoInfo->link,
		// 	"player" => $videoInfo->player,
		// 	"create_time" => $this->nowtime,
		// ];
		// $youkuVideoDao->baseAddData($data);

		return $videoInfo;
	}

	public function zzSetCsrf() {
		$csrfValue = randstr(8);
		$this->assign("csrfValue", $csrfValue);
		$verifyCsrf = getVerify($csrfValue);
		//echo 'csrfValue:'.$csrfValue.';生成的verifyCsrf:'.$verifyCsrf;
		cookie("csrfcookie2", $csrfValue);

		//D('Aaaa')->data(array('flag'=>'zzSetCsrf', 'content'=>$csrfValue, 'extra'=>$verifyCsrf))->add();

		$this->assign("formhash", $verifyCsrf);
	}

	public function zzCheckCsrf($checkOnce = 1) {
		$formhash = input("post.formhash", '', 'pwEscape');
		if (!$formhash) {
			$this->error('post的csrf不存在');
		}
		$csrfValue = cookie("csrfcookie2");
		if (!$csrfValue) {
			//$this->errorAjax('csrfValue竟然为空');
			$this->error('防止页面重复提交，请刷新页面重试');
		}
		$verifyCsrf = getVerify($csrfValue);

		//D('Aaaa')->data(array('flag'=>'zzCheckCsrf', 'content'=>$csrfValue, 'extra'=>$verifyCsrf, 'extra2'=>$formhash))->add();

		//echo 'csrfValue;'.$csrfValue.';生成的verifyCsrf:'.$verifyCsrf.';post过来的:'.$requestCsrf;exit;
		if ($formhash != $verifyCsrf) {
			//cookie("csrfcookie2", NULL); //验证完清空cookie
			//$this->errorAjax('防止页面重复提交，请请刷新页面重试'.$csrfValue);
			$this->error('防止页面重复提交，请请刷新页面重试 formhash:'.$formhash.';csrfValue:'.$csrfValue.';verifyCsrf:'.$verifyCsrf);
		}

		if ($checkOnce) {
			cookie("csrfcookie2", NULL); //验证完清空cookie
		}
		//return false;
	}

	//admin成功跳转
	public function adminSuccess($message, $jumpUrl='') {
		$this->assign('message', $message);
		$this->assign('jumpUrl', $jumpUrl);
		$this->assign('waitSecond', 2);
		echo $this->fetch(THEME_PATH."public/admin_success.html")->getContent();exit;
	}

	//admin错误提示
	public function adminError($message, $jumpUrl='') {
		$this->assign('message', $message);
		$this->assign('jumpUrl', $jumpUrl);
		echo $this->fetch(THEME_PATH."public/admin_error.html")->getContent();exit;
	}
	
	//pc成功跳转
	public function pcSuccess($message, $jumpUrl='') {
		$this->assign('message', $message);
		$this->assign('jumpUrl', $jumpUrl);
		$this->assign('waitSecond', 2);
		echo $this->fetch(THEME_PATH."public/pc_success.html")->getContent();exit;
	}

	//pc错误提示
	public function pcError($message, $jumpUrl='') {
		$this->assign('message', $message);
		$this->assign('jumpUrl', $jumpUrl);
		echo $this->fetch(THEME_PATH."public/pc_error.html")->getContent();exit;
	}

	protected function jsonResult($code, $msg, $data='') {
		@header("Content-Type:text/html; charset=utf-8");
		$result = array(
			'code' 		=> $code,
			'msg'		=> $msg,
			'data'		=> $data,
		);
		echo json_encode($result);exit;
	}
	
    /**
     * 验证数据
     * @access protected
     * @param  array        $data     数据
     * @param  string|array $validate 验证器名或者验证规则数组
     * @param  array        $message  提示信息
     * @param  bool         $batch    是否批量验证
     * @return array|string|true
     * @throws ValidateException
     */
    protected function validate(array $data, string|array $validate, array $message = [], bool $batch = false)
    {
	    //echo 'data:';print_r($data);print_r($validate);print_r($message);exit;
        if (is_array($validate)) {
            $v = new Validate();
            $v->rule($validate);
        } else {
            if (strpos($validate, '.')) {
                // 支持场景
                [$validate, $scene] = explode('.', $validate);
            }
            $class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
            $v     = new $class();
            if (!empty($scene)) {
                $v->scene($scene);
            }
        }

        $v->message($message);

        // 是否批量验证
        if ($batch || $this->batchValidate) {
            $v->batch(true);
        }

        return $v->failException(true)->check($data);
    }

    /**
     * 模板变量赋值
     * @param array|string $name 模板变量
     * @param mixed|null $value 变量值
     */
    public function assign(array|string $name, mixed $value = null): void {
        View::assign($name, $value);
    }

    /**
     * 解析和获取模板内容 用于输出
     * @param string $template
     * @param array $vars
     * @param bool $layout 是否需要自动布局
     * @return string
     */
    public function fetch(string $template = '', array $vars = [], bool $layout = true): string {
        return View::fetch($template);
    }
    
}